package states;

import hypeerweb.Node;
import hypeerweb.Range;

/**
 * The Down pointing node state, where we check if the node
 * is a cap or if it has a smaller down pointer.
 *
 * @author brinkerhoff_kendra
 *
 */
public class DownPointingNodeState extends NodeState {

	/**
	 * Default constructor, sets the current state of the machine.
	 */
	public DownPointingNodeState() {
		STATE_ID = 2;
	}

	/**
	 * Determines if range.lowerBound has a down pointer with a smaller webid than range.upperBound. 
	 * 
	 * @pre range &ne; null
	 * @post result = UpPointingNodeState where upperBound' = lowerBound.smallestDownPointer and upperBound'.id < upperBound.id
	 * 		<br>OR
	 * 		<br>result = HypercubeCapNodeState if lowerBound is a cap node
	 * 		<br>OR
	 * 		<br>result = TerminalNodeState if lowerBound.parent.id + 1 == upperBound.id
	 * 		<br>OR
	 * 		<br>result = null, meaning that there is an error in the hypeerweb connections
	 */
	public final NodeState shrinkRange(final Range r) {
		range = r;

		Node lower = range.getLowerBound();

		if (isCapState(lower)) {
			return new HypercubeCapNodeState();
		}
		if (range.getRange() == 1) {
			return new TerminalNodeState();
		}

		Node upper = lower.getConnections().getSmallestDownPointer();

		if(upper == null) {
			return new UpPointingNodeState();
		}
		else if(upper.getWebId().getValue()
				> range.getUpperBound().getWebId().getValue()) {
			return null;
		}
		else {
			range.setUpperBound(upper);
		}

		return new UpPointingNodeState();
	}

	/**
	 * Determines whether or not the given node is the cap of the hypeerweb.
	 *
	 * @param node the node in question
	 * @return true ==> node.fold = 0
	 * 		   false otherwise
	 */
	private boolean isCapState(final Node node) {
		if (node.getFold() != null
				&& node.getFold().getWebId().getValue() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * @return "Down Pointing Node State"
	 */
	public final String toString() {
		return "Down Pointing Node State";
	}
}
